home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / buzzmachines_massive.exe / Dev / Geoffroy Notefilter SourceCode / NoteFilter.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-23  |  11.0 KB  |  512 lines

  1. /*
  2.  * NoteFilter
  3.  *
  4.  * a filter based on notes
  5.  * 
  6.  * feel free to tweak the code but please rename the machine to (YourName)nGeoffroy Notefilter II for instance
  7.  * and send it to me!
  8.  *
  9.  * it's my first machine so be cool, it's not very well coded :-)
  10.  * 
  11.  * (c) Geoffroy Montel 2002
  12.  * email : coder@minizza.com
  13.  */
  14.  
  15. /*
  16.   Version History:
  17.     1.0 Initial release
  18.   CHANGELOG:
  19.   -
  20.   */
  21.  
  22. #include "NoteFilter.h"
  23. #include "../dsplib.h"
  24.  
  25. DLL_EXPORTS
  26.  
  27. // Buzz code starts here
  28.  
  29. // constructor
  30. mi::mi() {
  31. #if (miBETAWARNING)> 0
  32.     firstTick=true;
  33. #endif
  34. #if miNUMGLOBALPARAMETERS>0
  35.     GlobalVals = &gval;
  36. #endif
  37. #if (miNUMATTRIBUTES + miBETAWARNINGATTRIBUTE )>0
  38.     AttrVals = (int *)&aval;
  39. #else
  40.     AttrVals = NULL;
  41. #endif
  42. #if (miMAX_TRACKS>0 && miNUMTRACKPARAMETERS>0)
  43.     TrackVals = tval;
  44.     miNumberOfTracks=0;
  45. #else 
  46.     TrackVals = NULL;
  47. #endif
  48.  
  49.     // insert your code below
  50.  
  51.     trackBufferTempSize = 4096;
  52.     trackBufferTemp = (float *)malloc(trackBufferTempSize*sizeof(float));
  53.  
  54.     mixBufferTempSize = 4096;
  55.     mixBufferTemp = (float *)malloc(mixBufferTempSize*sizeof(float));
  56.  
  57.     // end of insert
  58. }
  59.  
  60.  
  61. // destructor
  62. mi::~mi() {
  63.     // free all allocated buffers here
  64.     free(trackBufferTemp);
  65.     free(mixBufferTemp);
  66. }
  67.  
  68.  
  69. // prepare everything, first Tick and AttributesChanged called _after_ this function
  70. void mi::MDKInit(CMachineDataInput * const pi) {
  71. #if miISALWAYSSTEREO > 0
  72.         SetOutputMode(true);
  73. #endif
  74. #if miNOTIFYONSAMPLERATECHANGES > 0
  75.     samplerate=pMasterInfo->SamplesPerSec;
  76. #endif
  77.  
  78.     // insert your own code here which inits the global parameters
  79.  
  80.     // update with the unit
  81.     unitChanged();
  82.  
  83.     a.setUnit(BuzzParameterUnit_MS);
  84.     d.setUnit(BuzzParameterUnit_MS);
  85.     s.setUnit(BuzzParameterUnit_MS);
  86.     r.setUnit(BuzzParameterUnit_MS);
  87.  
  88.     // update samplerate & samplePerTick
  89.     inertia.setSampleRate(samplerate);
  90.     samplesPerTick = pMasterInfo->SamplesPerTick;
  91.     inertia.setSamplesPerTick(samplesPerTick);
  92.  
  93.     inertiaChanged();
  94.     
  95.     // end of insert
  96.  
  97. #if (miMAX_TRACKS>0 && miNUMTRACKPARAMETERS>0)
  98.     for (int c = 0; c < miMAX_TRACKS; c++)
  99.     {
  100.         mytvals *mytv=mytval+c;
  101.     // insert your own code here which inits the track parameters
  102.         // mytv->xx = paraXX.DefValue
  103.  
  104.         mytv->noteFilterTrack.setSampleRate(samplerate);
  105.         mytv->noteFilterTrack.setQ(&q);
  106.         mytv->noteFilterTrack.setHarmoVolumes(harmoVolumes);
  107.         mytv->noteFilterTrack.setADSR(&a,&d,&s,&r);
  108.         mytv->volume.setSliderValue(BuzzParameterVolume.MAX_SLIDER_VALUE);
  109.         mytv->noteFilterTrack.setVolume(&(mytv->volume));
  110.     // end of insert
  111.     }
  112. #endif
  113.  
  114. }
  115.  
  116. #if (miMAX_TRACKS>0 && miNUMTRACKPARAMETERS>0)
  117. // track number has changed, update your track variables
  118. void mi::SetNumTracks(int const n) {
  119.     miNumberOfTracks=n;
  120.     // insert your own code below, if needed
  121.  
  122.  
  123.  
  124.     // end of insert
  125. }
  126. #endif
  127.  
  128. // user has selected some menu options
  129. void mi::Command(int const i) {
  130.     switch(i)
  131.     {
  132.     case 0:
  133.         pCB->MessageBox(miABOUTTXT);
  134.         break;
  135.     }
  136. }
  137.  
  138. // user has changed attributes, called after MDKInit()
  139. void mi::AttributesChanged() {
  140.     // check all the attributes in aval
  141.     // aval.time // and so on...
  142.     
  143.     
  144. }
  145.  
  146. // Describe the parameters
  147. char const *mi::DescribeValue(int const param, int const value) {
  148.     static char txt[50];
  149.     txt[0]=0;
  150.  
  151.     switch(param) {
  152.  
  153.     case PARAM_FILTERTYPE:
  154.         return filterType.toString(value);
  155.         break;
  156.  
  157.     case PARAM_Q:
  158.         return q.toString(value);
  159.         break;
  160.  
  161.     case PARAM_INERTIA:
  162.         return inertia.toString(value);
  163.         break;
  164.  
  165.     case PARAM_UNIT:
  166.         return unit.toString(value);
  167.         break;
  168.  
  169.     case PARAM_VOLUMEHARMO_0:
  170.     case PARAM_VOLUMEHARMO_1:
  171.     case PARAM_VOLUMEHARMO_2:
  172.     case PARAM_VOLUMEHARMO_3:
  173.     case PARAM_VOLUMEHARMO_4:
  174.     case PARAM_VOLUMEHARMO_5:
  175.     case PARAM_VOLUMEHARMO_6:
  176.     case PARAM_VOLUMEHARMO_7:
  177.     case PARAM_VOLUMEHARMO_8:
  178.     case PARAM_VOLUMEHARMO_9:
  179.         
  180.         return harmoVolumes[param-PARAM_VOLUMEHARMO_0].toString(value);
  181.         break;
  182.  
  183.     case PARAM_SWITCH_ADSR:
  184.         return switchADSR.toString(value);
  185.         break;
  186.  
  187.     case PARAM_A:
  188.     case PARAM_D:
  189.     case PARAM_S:
  190.     case PARAM_R:
  191.         return a.toString(value);
  192.         break;
  193.  
  194.     case PARAM_TRACK_VOLUME:
  195.         return harmoVolumes[0].toString(value);
  196.  
  197.     default:
  198.         sprintf(txt,"** ERROR **");
  199.     
  200.     }
  201.  
  202.     return txt;
  203. }
  204.  
  205. // machine input has changed mono<->stereo
  206. void mi::OutputModeChanged(bool stereo) {
  207.     
  208. }
  209.  
  210. void mi::MidiNote(int const channel, int const value, int const velocity) {
  211.     
  212. }
  213.  
  214. void mi::Stop() {
  215.     
  216. }
  217.  
  218. // what to update when the inertia changes
  219. void mi::inertiaChanged()
  220. {
  221.     // q has inertia
  222.     this->q.setInertia(inertia.getRealValue());
  223.  
  224.     // harmonics volumes have inertia
  225.     for (int i=0;i<NoteFilterTrack_NB_HARMONICS;i++) {
  226.         harmoVolumes[i].setInertia(inertia.getRealValue());
  227.     }
  228.  
  229. }
  230.  
  231. // what to update when the unit changes
  232. void mi::unitChanged()
  233. {
  234.     inertia.setUnit(unit.getRealValue());
  235.     inertiaChanged();
  236.  
  237.     /*
  238.     a.setUnit(unit.getRealValue());
  239.     d.setUnit(unit.getRealValue());
  240.     s.setUnit(unit.getRealValue());
  241.     r.setUnit(unit.getRealValue());
  242.     */
  243. }
  244.  
  245. void mi::filterTypeChanged()
  246. {
  247.     if (filterType.getRealValue() == BuzzParameterFilterType_BPF) {
  248.         q.MIN_REAL_VALUE = 1.0f;
  249.         q.MAX_REAL_VALUE = 127.0f;
  250.     } else if (filterType.getRealValue() == BuzzParameterFilterType_NOTCH) {
  251.         q.MIN_REAL_VALUE = 0.01f;
  252.         q.MAX_REAL_VALUE = 2.0f;
  253.     } else if (filterType.getRealValue() == BuzzParameterFilterType_PEAK) {
  254.         q.MIN_REAL_VALUE = 0.01f;
  255.         q.MAX_REAL_VALUE = 10.0f;
  256.     }
  257. }
  258.  
  259.  
  260. // check for updated parameters, called every tick
  261. void mi::Tick() {
  262.  
  263. #if miNOTIFYONSAMPLERATECHANGES > 0
  264.     if(pMasterInfo->SamplesPerSec != samplerate) {
  265.     // insert your code below which handles the change in the samplerate
  266.  
  267.         samplerate = pMasterInfo->SamplesPerSec;
  268.  
  269.         for (int c = 0; c < miMAX_TRACKS; c++)
  270.         {
  271.             mytvals *mytv=mytval+c;
  272.             mytv->noteFilterTrack.setSampleRate(samplerate);
  273.         }
  274.  
  275.         inertia.setSampleRate(samplerate);
  276.         inertiaChanged();
  277.  
  278.     // end of insert
  279.     }
  280. #endif
  281.  
  282.     if(pMasterInfo->SamplesPerTick != samplesPerTick) {
  283.         samplesPerTick = pMasterInfo->SamplesPerTick;
  284.         inertia.setSamplesPerTick(samplesPerTick);
  285.         inertiaChanged();
  286.     }
  287. /*
  288. // example
  289.   if (gval.xx != paraXX.NoValue) {
  290.       =gval.xx;
  291.   }
  292.   */
  293.  
  294.  
  295.     // insert your code below
  296.  
  297.     if (gval.filtertype != paraFilterType.NoValue) {
  298.         this->filterType.setSliderValue(gval.filtertype);
  299.         for (int c = 0; c < miMAX_TRACKS; c++)
  300.         {
  301.             mytvals *mytv=mytval+c;
  302.             mytv->noteFilterTrack.setFilterType(filterType.getRealValue());
  303.         }
  304.  
  305.         filterTypeChanged();
  306.  
  307.     }
  308.  
  309.     if (gval.unit != paraUnit.NoValue) {
  310.         this->unit.setSliderValue(gval.unit);
  311.         /*
  312.         this->inertia.setUnit(unit.getRealValue());
  313.         inertiaChanged();
  314.         */
  315.         unitChanged();
  316.     }
  317.  
  318.     if (gval.inertia != paraInertia.NoValue) {
  319.         this->inertia.setSliderValue(gval.inertia);
  320.         this->q.setInertia(inertia.getRealValue());
  321.         inertiaChanged();
  322.     }
  323.  
  324.     if (gval.q != paraQ.NoValue) {
  325.         this->q.setSliderValue(gval.q);
  326.     }
  327.  
  328.     for (int i=0;i<NoteFilterTrack_NB_HARMONICS;i++) {
  329.         if (gval.harmovolume[i] != paraVolumeHarmo0.NoValue) {
  330.             this->harmoVolumes[i].setSliderValue(gval.harmovolume[i]);
  331.         }
  332.     }
  333.  
  334.     if (gval.switchADSR != paraSwitchADSR.NoValue) {
  335.         this->switchADSR.setSliderValue(gval.switchADSR);
  336.         for (int c = 0; c < miNumberOfTracks; c++) {
  337.             mytvals *mytv=mytval+c;
  338.             mytv->noteFilterTrack.activateADSR(this->switchADSR.getRealValue());
  339.         }
  340.  
  341.     }
  342.  
  343.     if (gval.a != paraA.NoValue) {
  344.         this->a.setSliderValue(gval.a);
  345.     }
  346.  
  347.     if (gval.d != paraD.NoValue) {
  348.         this->d.setSliderValue(gval.d);
  349.     }
  350.  
  351.     if (gval.s != paraS.NoValue) {
  352.         this->s.setSliderValue(gval.s);
  353.     }
  354.  
  355.     if (gval.r != paraR.NoValue) {
  356.         this->r.setSliderValue(gval.r);
  357.     }
  358.  
  359.     // end of insert
  360.  
  361.  
  362. // if you have multiple track support, this part will be compiled in
  363. #if (miMAX_TRACKS>0 && miNUMTRACKPARAMETERS>0)
  364.     for (int c = 0; c < miNumberOfTracks; c++) {
  365.         tvals *tv=tval+c;
  366.         mytvals *mytv=mytval+c;
  367.         /*
  368.         if (tv->xx != paraXX.NoValue) {
  369.             =tv->xx;
  370.         }
  371.         */
  372.  
  373.         // insert your code for parsing track effects below, tv->value for each parameter
  374.         if (tv->note != paraNote.NoValue) {
  375.             mytv->noteFilterTrack.setNote(tv->note);
  376.         }
  377.  
  378.         if (tv->volume != paraTrackVolume.NoValue) {
  379.             mytv->volume.setSliderValue(tv->volume);
  380.         }
  381.  
  382.         // end of insert
  383.     
  384.     }
  385. #endif
  386.  
  387. #if (miBETAWARNING) > 0
  388.   if(firstTick) {
  389.     firstTick=false;
  390.  
  391. #if miBETAWARNING > 0
  392.     if(aval.betawarning==0)
  393.         pCB->MessageBox(miBETAWARNINGTXT);
  394. #endif
  395.  
  396.   }
  397. #endif
  398.  
  399.  
  400.  
  401. bool mi::MDKWorkStereo(float *psamples, int numsamples, int const mode) {
  402.     /*
  403.      * update parameters with inertia
  404.      */
  405.     
  406.     q.timeGoesBy(numsamples);
  407.     for (int i=0;i<NoteFilterTrack_NB_HARMONICS;i++) {
  408.         this->harmoVolumes[i].timeGoesBy(numsamples);
  409.     }
  410.  
  411.     if (mode==WM_NOIO) {
  412.         // machine is not connected to anything
  413.         return false;
  414.     } else
  415.  
  416.     if (mode==WM_WRITE) {
  417.         // no sound coming in
  418.         // generators make the sound here
  419.         // - return true when sound has been produced
  420.         // - return false for silence
  421.         // effects (like delays) can produce sound here too
  422.         // - return true if sound has been made, false otherwise
  423.         return false;
  424.     } else
  425.     
  426.     if (mode == WM_READ) {
  427.         // <thru> set in the sequence editor
  428.         // machine can read the stream but not write
  429.         // return true always
  430.         return true;
  431.     }
  432.  
  433.     // effects handle sound here usually
  434.     // return true always, except false when you want to silence the output
  435.     
  436.     // see if the temporary buffer is large enough
  437.     if (numsamples * 2 > trackBufferTempSize) {
  438.         realloc(trackBufferTemp,numsamples * 2 * sizeof(float));
  439.         realloc(mixBufferTemp,numsamples * 2 * sizeof(float));
  440.         trackBufferTempSize = numsamples;
  441.         mixBufferTempSize = numsamples;
  442.     }
  443.  
  444.     // zero the mixBuffer
  445.     DSP_Zero(mixBufferTemp,numsamples*2);
  446.  
  447.     // process each track
  448.     for (int c = 0; c < miNumberOfTracks; c++) {
  449.         tvals *tv=tval+c;
  450.         mytvals *mytv=mytval+c;
  451.  
  452.         // copy the samples in the temporary buffer
  453.         DSP_Copy(trackBufferTemp, psamples, numsamples*2);
  454.  
  455.         // process it
  456.         mytv->noteFilterTrack.MDKWorkStereo(trackBufferTemp,numsamples,mode);
  457.         
  458.         // mix it with the output
  459.         DSP_Add(mixBufferTemp,trackBufferTemp,numsamples*2);
  460.     }
  461.  
  462.     // copy the output to psamples
  463.     DSP_Copy(psamples, mixBufferTemp, numsamples*2);
  464.  
  465. /*
  466.     do {
  467.         psamples[0]=psamples[0];
  468.         psamples[1]=psamples[1];
  469.         psamples+=2;
  470.     } while(--numsamples);
  471. */
  472.     return true;
  473. }
  474.  
  475. bool mi::MDKWork(float *psamples, int numsamples, int const mode) {
  476.     
  477.     if (mode==WM_NOIO) {
  478.         // machine is not connected to anything
  479.         return false;
  480.     } else
  481.  
  482.     if (mode==WM_WRITE) {
  483.         // no sound coming in
  484.         // generators make the sound here
  485.         // - return true when sound has been produced
  486.         // - return false for silence
  487.         // effects (like delays) can produce sound here too
  488.         // - return true if sound has been made, false otherwise
  489.         return false;
  490.     } else
  491.  
  492.     if (mode == WM_READ) {
  493.         // <thru> set in the sequence editor
  494.         // machine can read the stream but not write
  495.         // return true always
  496.         return true;
  497.     }
  498.  
  499.     // effects handle sound here usually
  500.     // return true always, except false when you want to silence the output
  501.  
  502. /*
  503.     do {
  504.         psamples[0]=psamples[0];
  505.         psamples++;
  506.     } while(--numsamples);
  507. */
  508.     return true;
  509. }
  510.  
  511.